<!DOCTYPE html>
<html lang="en">
<head>
    <title>Notification Demo</title>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <link rel="stylesheet" type="text/css" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" >

    <script type="text/javascript">
        /*
         * This is a sample javascript code to connect to a notification channel using websocket.
         * Please note that your browser application must implement the following:
         * 1. Connection URL is /ws/{notification}/{token}
         *    where "notification" is the name of the sample notification backend app and
         *    token should be an access token for the notification channel.
         * 2. Keep-alive protocol.
         */

        var msg = [];
        var max_items = 15;
        var connected = false;
        var ws;
        var ping = null;
        /*
         * KEEP-ALIVE PROTOCOL
         *
         * WebSocket connection is persistent, and it is important to tell the backend that your browser application
         * is not stalled. Keep-alive protocol also allows your browser app to detect if notification backend service
         * is offline. When backend is offline, the browser app can inform the user and retry the connection.
         *
         * The standard websocket timeout is 60 seconds. We recommend setting the keep-alive interval
         * between 20-30 seconds.
         */
        var pingInterval = 30000;

        function show(input) {
            // push input as the first item in the array
            msg.unshift(input);
            while (msg.length > max_items) {
                msg.pop();
            }
            var s = ''
            for (i in msg) {
                s += msg[i];
                s += '\n';
            }
            document.getElementById('message').innerHTML = s;
        }

        function disconnectFromEdge() {
            if (connected) {
                ws.close();
            } else {
                show(eventWithTimestamp("error", "Already disconnected"));
            }
        }

        function subscribeTopic(add) {
            var topic = document.getElementById('topic').value.trim();
            if (topic.length == 0) {
               show(eventWithTimestamp("error", "Missing topic"));
            } else {
                var s = {}
                s['type'] = add? 'subscribe' : 'unsubscribe';
                s['topic'] = topic;
                ws.send(JSON.stringify(s, null, 2));
            }
        }

        function publishTopic() {
            var topicMessage = document.getElementById('topic').value.trim();
            if (topicMessage.length == 0) {
               show(eventWithTimestamp("error", "Missing topic:message"));
            } else {
                var colon = topicMessage.indexOf(':');
                if (colon > 0 && topicMessage.length) {
                    var topic = topicMessage.substring(0, colon).trim();
                    var message = topicMessage.substring(colon+1).trim();
                    if (topic.length == 0 || message.length == 0) {
                       show(eventWithTimestamp("error", "Input format should be topic:message"));
                    } else {
                        var s = {}
                        s['type'] = 'publish';
                        s['topic'] = topic;
                        s['message'] = message;
                        ws.send(JSON.stringify(s, null, 2));
                    }
                } else {
                    show(eventWithTimestamp("error", "Input format should be topic:message"));
                }
            }
        }

        function keepAlive() {
            if (connected) {
                ws.send(eventWithTimestamp("hello", "keep alive"));
                ping = setTimeout(keepAlive, pingInterval);
            }
        }

        function eventWithTimestamp(msg_type, message) {
            var s = {}
            s['type'] = msg_type;
            s['message'] = message;
            s['time'] = (new Date()).toISOString();
            return JSON.stringify(s, null, 2);
        }

        function resume() {
            document.getElementById('message').style.display = "none";
            document.getElementById('resume').style.display = "none";
            document.getElementById('connect').style.display = "inline"
        }

        function connectToEdge() {

            if ("WebSocket" in window) {
                document.getElementById('message').style.display = "block";
                var token = document.getElementById('token').value;
                if (token.length == 0) {
                    show(eventWithTimestamp("error", "missing token"));
                    document.getElementById('resume').style.display = "inline";
                    document.getElementById('connect').style.display = "none"
                    return;
                }
                if (connected) {
                    show(eventWithTimestamp("error", "already connected"));
                    document.getElementById('resume').style.display = "inline";
                    document.getElementById('connect').style.display = "none"
                    return;
                }
                // open a web socket
                var protocol = window.location.protocol == "http:"? "ws" : "wss";
                ws = new WebSocket(protocol+"://"+window.location.host+"/ws/notification/"+token);

                ws.onopen = function() {
                    show(eventWithTimestamp("info", "connected"));
                    connected = true;
                    document.getElementById('connect').style.display = "none"
                    document.getElementById('disconnect').style.display = "inline"
                    ping = setTimeout(keepAlive, pingInterval);
                };

                ws.onmessage = function(evt) {
                    // TODO: put your business logic to handle the notification event here
                    show(evt.data);
                };

                ws.onclose = function(evt) {
                    connected = false;
                    clearTimeout(ping);
                    show(eventWithTimestamp("info", "disconnected - ("+evt.code+") "+evt.reason));
                    document.getElementById('message').style.display = "block";
                    document.getElementById('resume').style.display = "inline";
                    document.getElementById('connect').style.display = "none"
                    document.getElementById('disconnect').style.display = "none";
                };

            }  else {
                show("WebSocket NOT supported by your Browser");
            }
        }
      </script>

</head>
<body>

<div class="container">

    <h4 style="color: #3cb371">Notification Demo</h4>
    To run this demo, get a websocket access token from "/api/ws/token" and use the token value in the input box.
    <br/>
    Enter the token value here and click "Start Service".
    <br/>
    Once connected, you can subscribe/unsubscribe or publish to any notification topic.
    <br/><br/>
    <div id="connect">
        <div class="input-group">
            <div class="input-group mb-3">
                <div class="input-group-prepend">
                    <span class="input-group-text">Token</span>
                </div>
                <input id="token" type="text" class="form-control" name="app" placeholder="token value here">
            </div>
        </div>
        <div style="height: 10px"></div>
        <button type="button" class="btn btn-primary" onclick="javascript:connectToEdge()">Start Service</button>
    </div>
    <div id="disconnect" style="display: none">
        <div class="input-group">
            <div class="input-group mb-3">
                <div class="input-group-prepend">
                    <span class="input-group-text">Topic</span>
                </div>
                <input id="topic" type="text" class="form-control" name="topic" placeholder="topic or topic:message">
            </div>
        </div>
        <div style="height: 10px"></div>
        <button type="button" class="btn btn-primary" onclick="javascript:subscribeTopic(true)">Subscribe</button>
        <button type="button" class="btn btn-secondary" onclick="javascript:subscribeTopic(false)">Unsubscribe</button>
        <button type="button" class="btn btn-primary" onclick="javascript:publishTopic()">Publish</button>
        <button type="button" class="btn btn-warning" onclick="javascript:disconnectFromEdge()">Stop Service</button>
    </div>

    <button id="resume" style="display: none" type="button" class="btn btn-warning" onclick="javascript:resume()">Continue</button>
    <hr>
    <pre id="message" class="border border-success rounded" style="background-color: #3c3c3c; color: white; display: none;"></pre>
</div>

</body>
</html>